package es.uned.etsii.si3.taller.servlets;

import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.struts2.interceptor.SessionAware;

import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import com.opensymphony.xwork2.ActionSupport;

import es.uned.etsii.si3.taller.Cliente;
import es.uned.etsii.si3.taller.EmpleadoTaller;
import es.uned.etsii.si3.taller.FactoriaDAO;
import es.uned.etsii.si3.taller.FactoriaFunciones;
import es.uned.etsii.si3.taller.ParteTrabajo;
import es.uned.etsii.si3.taller.Reparacion;
import es.uned.etsii.si3.taller.Seccion;
import es.uned.etsii.si3.taller.Taller;
import es.uned.etsii.si3.taller.TipoSeccion;
import es.uned.etsii.si3.taller.Trabajo;
import es.uned.etsii.si3.taller.Usuario;
import es.uned.etsii.si3.taller.Vehiculo;
import es.uned.etsii.si3.taller.misc.ProporcionaFuncionalidad;

public class PTPlanificar extends ActionSupport implements SessionAware {
	
	private static final long serialVersionUID = 1L;
	
	private 	Map<String, Object>		userSession;
	
	private 	String				descripcion;
	public 		String				getDescripcion()							{ return this.descripcion; }
	public 		void				setDescripcion(String s)					{ this.descripcion = s; }

	private		String				fechaEstimadaString;
	public 		String				getFechaEstimadaString()					{ return this.fechaEstimadaString; }
	public 		void				setFechaEstimadaString(String s)			{ this.fechaEstimadaString = s; }
	
	private 	ParteTrabajo		parteSeleccionado = null;
	public 		ParteTrabajo		getParteSeleccionado() 						{ return this.parteSeleccionado; }
	public 		void				setParteSeleccionado(ParteTrabajo pT) 		{ this.parteSeleccionado = pT; }

	private 	static int 			parteSeleccionadoID = -1;
	public 		int					getParteSeleccionadoID() 					{ return PTPlanificar.parteSeleccionadoID; }
	public 		void				setParteSeleccionadoID(int i) 				{ PTPlanificar.parteSeleccionadoID = i; }

	private 	Cliente  			clienteSeleccionado;
	public 		Cliente 	 		getClienteSeleccionado() 					{ return this.clienteSeleccionado; }
	public 		void      			setClienteSeleccionado(Cliente c) 			{ this.clienteSeleccionado = c; }

	private 	static int			clienteSeleccionadoID = -1;
	public 		int  				getClienteSeleccionadoID() 					{ return PTPlanificar.clienteSeleccionadoID; }
	public 		void		 		setClienteSeleccionadoID(int i) 			{ PTPlanificar.clienteSeleccionadoID = i; }
	
	private 	Vehiculo  			vehiculoSeleccionado;
	public 		Vehiculo 	 		getVehiculoSeleccionado() 					{ return this.vehiculoSeleccionado; }
	public 		void      			setVehiculoSeleccionado(Vehiculo v)			{ this.vehiculoSeleccionado = v; }

	private 	static int			vehiculoSeleccionadoID = -1;
	public 		int 				getVehiculoSeleccionadoID() 				{ return PTPlanificar.vehiculoSeleccionadoID; }
	public 		void				setVehiculoSeleccionadoID(int i) 			{ PTPlanificar.vehiculoSeleccionadoID = i; }
	
	private 	Reparacion			reparacionSeleccionado = null;
	public 		Reparacion			getReparacionSeleccionado()					{ return this.reparacionSeleccionado; }
	public 		void				setReparacionSeleccionado(Reparacion r)		{ this.reparacionSeleccionado = r; }

	private 	static int 			reparacionSeleccionadoID = -1;
	public 		int					getReparacionSeleccionadoID() 				{ return PTPlanificar.reparacionSeleccionadoID; }
	public 		void				setReparacionSeleccionadoID(int i) 			{ PTPlanificar.reparacionSeleccionadoID = i; }
	
	private 	Seccion				seccionSeleccionado = null;
	public 		Seccion				getSeccionSeleccionado()					{ return this.seccionSeleccionado; }
	public 		void				setSeccionSeleccionado(Seccion s)			{ this.seccionSeleccionado = s; }

	private 	static int 			seccionSeleccionadoID = -1;
	public 		int					getSeccionSeleccionadoID() 					{ return PTPlanificar.seccionSeleccionadoID; }
	public 		void				setSeccionSeleccionadoID(int i) 			{ PTPlanificar.seccionSeleccionadoID = i; }

	private 	Trabajo				trabajoSeleccionado = null;
	public 		Trabajo				getTrabajoSeleccionado() 					{ return this.trabajoSeleccionado; }
	public 		void				setTrabajoSeleccionado(Trabajo t) 			{ this.trabajoSeleccionado = t; }
		
	private 	static int 			trabajoSeleccionadoID = -1;
	public 		int					getTrabajoSeleccionadoID() 					{ return PTPlanificar.trabajoSeleccionadoID; }
	public 		void				setTrabajoSeleccionadoID(int i) 			{ PTPlanificar.trabajoSeleccionadoID = i; }

	private 	List<ParteTrabajo>	listaPartes;		
	public		List<ParteTrabajo>	getListaPartes() 							{ return this.listaPartes; }
	public 		void				setListaPartes(List<ParteTrabajo> l)		{ this.listaPartes = l; }

	private 	List<Reparacion> 	listaReparaciones = null;
	public 		List<Reparacion>	getListaReparaciones()						{ return this.listaReparaciones; }
	public 		void 				setListaReparaciones(List<Reparacion> l)	{ this.listaReparaciones = l; }

	private 	List<Seccion>		listaSecciones;
	public 		List<Seccion>		getListaSecciones()							{ return this.listaSecciones; }
	public 		void				setListaSecciones(List<Seccion> l)			{ this.listaSecciones = l; }

	private 	int					siguiente;
	public 		int					getSiguiente()								{ return this.siguiente; }
	public		void				setSiguiente(int i)							{ this.siguiente = i; }
	//1:"pTPlanServicios"
	//2:"pantallaJTVerPlanificaciones"

	
	
	/**
	 * Muestra las planificaciones existentes
	 * @return  actionerror
	 */
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.JEFE_TALLER_VER_PLANIFICACIONES)	
	public String pTVerPlanificaciones() {
		String res = SUCCESS;
		try {
			QueryBuilder<ParteTrabajo, Integer> parteQb = FactoriaDAO.getDao(ParteTrabajo.class).queryBuilder();
			Where<ParteTrabajo, Integer> wParteQb = parteQb.where();
			wParteQb.eq(ParteTrabajo.ID_TALLER_FIELD_NAME, this.getTallerSesionEmpleado());
			wParteQb.and().eq(ParteTrabajo.ACEPTADO_FIELD_NAME, true);
			wParteQb.and().eq(ParteTrabajo.VISTOBUENO_FIELD_NAME, false);
			QueryBuilder<Vehiculo, Integer> vehiculoQb = FactoriaDAO.getDao(Vehiculo.class).queryBuilder();
			QueryBuilder<ParteTrabajo, Integer> parJOINveh = parteQb.join(vehiculoQb);			
			QueryBuilder<Reparacion, Integer> reparacionQb = FactoriaDAO.getDao(Reparacion.class).queryBuilder();						
			this.listaPartes = parJOINveh.join(reparacionQb).distinct().orderBy(Reparacion.FECHAESTIMADA_FIELD_NAME, true).query();			
		} catch (SQLException e) {
			addActionError("Error al localizar los partes programados: " + e);
			res = ERROR;
		}		
		return res;
	}

	/**
	 * Obtiene los detalles de una planificación dada
	 * @return  actionerror
	 * @throws SQLException
	 */
	public String pTDetallePlanificacion() throws SQLException {
		String res = this.recuperarDatosParte();
		try {			
			QueryBuilder<ParteTrabajo, Integer> parteQb = FactoriaDAO.getDao(ParteTrabajo.class).queryBuilder();;
			Where<ParteTrabajo, Integer> wParteQb = parteQb.where();
			wParteQb.eq(ParteTrabajo.ID_FIELD_NAME, this.getParteSeleccionadoID());
			
			
			QueryBuilder<Seccion, Integer> seccionQb = FactoriaDAO.getDao(Seccion.class).queryBuilder();
			QueryBuilder<TipoSeccion, Integer> tipoSeccionQb = FactoriaDAO.getDao(TipoSeccion.class).queryBuilder();
			QueryBuilder<Seccion, Integer> secJOINts = seccionQb.join(tipoSeccionQb);
			
			QueryBuilder<Reparacion, Integer> reparacionQb = FactoriaDAO.getDao(Reparacion.class).queryBuilder();
			QueryBuilder<Reparacion, Integer> repJOINsec = reparacionQb.join(secJOINts);
			
			this.listaReparaciones = repJOINsec.join(parteQb).distinct().orderBy(Reparacion.FECHAESTIMADA_FIELD_NAME, true).query();
			
		} catch (SQLException e) {
			addActionError("Error al localizar los partes programados: " + e);
			res = ERROR;
		}		
		return res;
	}

	/**
	 * Graba una nueva planificación (objeto reparación) 
	 * @return  actionerror
	 */
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.JEFE_TALLER_PLANIFICAR_REPARACION)	
	public String pTPlanificarReparacion() {
		String res = SUCCESS;
		try {
			//Condiciones: albaran="EnTaller", VB=false, NO tenga reparaciones programadas
			QueryBuilder<ParteTrabajo, Integer> parteQb = FactoriaDAO.getDao(ParteTrabajo.class).queryBuilder();
			Where<ParteTrabajo, Integer> wParteQb = parteQb.where();
			wParteQb.eq(ParteTrabajo.ID_TALLER_FIELD_NAME, this.getTallerSesionEmpleado());
			wParteQb.and().eq(ParteTrabajo.VISTOBUENO_FIELD_NAME, false);
			wParteQb.and().eq(ParteTrabajo.ALBARAN_FIELD_NAME, "EnTaller");

			QueryBuilder<Vehiculo, Integer> vehiculoQb = FactoriaDAO.getDao(Vehiculo.class).queryBuilder();
			QueryBuilder<ParteTrabajo, Integer> parJOINveh = parteQb.join(vehiculoQb);
			
			List<ParteTrabajo> lPar = parJOINveh.query();			
			this.listaPartes = new ArrayList<ParteTrabajo>();
			ParteTrabajo pT = null;
			List<Reparacion> lRep = null;
			
			//NO tenga reparaciones programadas
			for ( int i=0; i < lPar.size(); i ++) {
				QueryBuilder<Reparacion, Integer> reparacionQb = FactoriaDAO.getDao(Reparacion.class).queryBuilder();
				Where<Reparacion, Integer> wReparacionQb = reparacionQb.where();
				wReparacionQb.eq(Reparacion.ID_PARTETRABAJO_FIELD_NAME, lPar.get(i).getId());
				lRep = reparacionQb.query();
				if ( lRep.size() < 1 ) {
					pT = lPar.get(i);
					this.listaPartes.add(pT);
				}
			}			
			
		} catch (SQLException e) {
			addActionError("Error al localizar los partes por planificar: " + e);
			res = ERROR;
		}		
		return res;
	}
	

	
	/** 
	 * Carga las secciones del taller
	 * @return  actionerror
	 * @throws SQLException
	 */
	public String pTPlanServicios() throws SQLException {
		String res = recuperarDatosParte();
		if ( res == SUCCESS ) {
			try {			
				QueryBuilder<Seccion, Integer> seccionQb = FactoriaDAO.getDao(Seccion.class).queryBuilder();
				Where<Seccion, Integer> wSeccionQb = seccionQb.where();
				wSeccionQb.eq(Seccion.ID_TALLER_FIELD_NAME, this.getTallerSesionEmpleado());			
				QueryBuilder<TipoSeccion, Integer> tipoSeccionQb = FactoriaDAO.getDao(TipoSeccion.class).queryBuilder();
				this.listaSecciones = seccionQb.join(tipoSeccionQb).query();				
			} catch (SQLException e) {
				addActionError("Error al localizar las secciones del taller: " + e);
				res = ERROR;
			}
		}
		return res;
	}
	
	/**
	 * Obtiene las secciones
	 * @return  actionerror
	 * @throws SQLException
	 */
	public String pTPlanificarSeccion() throws SQLException {
		String res = this.pTPlanServicios();
		ParteTrabajo pT = this.getParteSeleccionado();
		if ( res == SUCCESS ) {
			res = condicionesPrevias();
		}
		if ( res == SUCCESS ) {
			Usuario u = this.getParteSeleccionado().getUsuario();						
			this.setSeccionSeleccionado(FactoriaDAO.recuperar(Seccion.class, this.getSeccionSeleccionadoID()));
			Seccion s = this.getSeccionSeleccionado();
			
			String d = this.getDescripcion();
			SimpleDateFormat df = new SimpleDateFormat("dd/MM/yy");
			Date fEst = null;
			try {
				fEst = df.parse(this.getFechaEstimadaString());
			} catch (ParseException e) {
				addActionError("Fecha Estimada errónea: " + e);
				res = ERROR;								
			}
			new Reparacion();
			this.setReparacionSeleccionado( Reparacion.crear(u, s, pT, d, null, fEst, null, null, false, null));
			this.setSiguiente(1);
		}		
		return res;
	}
	
	/**
	 * Modifica un plan de reparaciones existente
	 * @return  actionerror
	 * @throws SQLException
	 */
	public String pTPlanPrevioModificar() throws SQLException {
		String res = SUCCESS;
		this.setReparacionSeleccionado(FactoriaDAO.recuperar(Reparacion.class, this.getReparacionSeleccionadoID()));
		this.setParteSeleccionado(this.getReparacionSeleccionado().getParteTrabajo());
		this.setParteSeleccionadoID(this.getParteSeleccionado().getId());
		this.setVehiculoSeleccionado(this.getParteSeleccionado().getVehiculo());
		this.setSeccionSeleccionado(this.getReparacionSeleccionado().getSeccion());
		this.setSeccionSeleccionadoID(this.getSeccionSeleccionado().getId());
		return res;
	}
	
	/**
	 * Permite modificar la sección 
	 * @return  actionerror
	 * @throws SQLException
	 */
	public String pTPlanificarModificarSeccion() throws SQLException {
		String res = recuperarDatosParte();
		this.setReparacionSeleccionado(FactoriaDAO.recuperar(Reparacion.class, this.getReparacionSeleccionadoID()));
		this.setParteSeleccionado(this.getReparacionSeleccionado().getParteTrabajo());
		this.setParteSeleccionadoID(this.getParteSeleccionado().getId());
		this.setVehiculoSeleccionado(this.getParteSeleccionado().getVehiculo());
		this.setSeccionSeleccionado(this.getReparacionSeleccionado().getSeccion());
		this.setSeccionSeleccionadoID(this.getSeccionSeleccionado().getId());
		if ( res == SUCCESS ) {
			res = condicionesPrevias();
		}
		if ( res == SUCCESS ) {
			SimpleDateFormat df = new SimpleDateFormat("dd/MM/yy");
			Date fEst = null;
			try {
				fEst = df.parse(this.getFechaEstimadaString());
			} catch (ParseException e) {
				addActionError("Fecha Estimada errónea: " + e);
				res = ERROR;								
			}
			this.setReparacionSeleccionado(FactoriaDAO.recuperar(Reparacion.class, getReparacionSeleccionadoID()));
			this.getReparacionSeleccionado().setDescripcion(this.getDescripcion());
			this.getReparacionSeleccionado().setFechaEstimada(fEst);
			this.getReparacionSeleccionado().update();
			this.setSiguiente(2);
		}		
		return res;
	}
	
	
	private String condicionesPrevias() {
		String res = SUCCESS;
		if ( this.getDescripcion().isEmpty() ) {
			addActionError("No ha indicado ninguna desripción");
			res = ERROR;
		}
		if ( this.getFechaEstimadaString().isEmpty() ) {
			addActionError("La fecha estimada de finalización es obligatoria");
			res = ERROR;				
		}
		return res;
	}

	
	private String recuperarDatosParte() throws SQLException {
		String res = SUCCESS;		
		this.setParteSeleccionado(FactoriaDAO.recuperar(ParteTrabajo.class, getParteSeleccionadoID()));
		this.setClienteSeleccionado(this.getParteSeleccionado().getUsuario().getCliente());
		this.setClienteSeleccionadoID(this.getClienteSeleccionado().getId());			
		this.setVehiculoSeleccionado(this.getParteSeleccionado().getVehiculo());
		this.setVehiculoSeleccionadoID(this.getVehiculoSeleccionado().getId());
		return res;
	}


	private Taller getTallerSesionEmpleado() {
		Taller res = null;
		Usuario uS = (Usuario) userSession.get("usuario");
		QueryBuilder<EmpleadoTaller, Integer> eTQb;
		try {
			eTQb = FactoriaDAO.getDao(EmpleadoTaller.class).queryBuilder();
			Where<EmpleadoTaller, Integer> wETQb = eTQb.where();			
			wETQb.eq(EmpleadoTaller.ID_USUARIO_FIELD_NAME, uS.getId());			
			List<EmpleadoTaller> lista = wETQb.query();
			res = lista.get(0).getTaller();
		} catch (SQLException e) {
			addActionError("Error al buscar taller: " + e);
		}			
		return res;
	}
	
	@Override
	public void setSession(Map<String, Object> session) {
		userSession = session;		
	}


}
